home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / splint.zip / SPLINT.C < prev    next >
C/C++ Source or Header  |  1993-05-19  |  10KB  |  410 lines

  1. /* Splint:
  2.  * a data compression program
  3.  *
  4.  * This program refers the Pascal source codes of
  5.  * a splay-prefix encoding program in an article of
  6.  *
  7.  * Jones, Douglas. W,:
  8.  * Application of Splay Trees to Data Compression,
  9.  * Communications ACM, Vol. 31, No. 8, pp. 996 - 1007. (August 1988)
  10.  *
  11.  * Written by Kenji Rikitake and Naoshi Wakatabe.
  12.  * Copyright (C)1988, 1989 by Kenji Rikitake and Naoshi Wakatabe.
  13.  * All rights reserved.
  14.  * Permission to copy this program without fee all or part of this
  15.  * material is granted, provided that the copies are not made or
  16.  * distributed for direct commercial advantage.
  17.  *
  18.  * If you have any questions and/or suggestions, Contact
  19.  *
  20.  * Kenji Rikitake
  21.  * 4-19-11-102, Sakurajousui, Setagaya-ku,
  22.  * Tokyo 156 Japan
  23.  * JUNET: rikitake%wadalab.t.u-tokyo.JUNET@relay.cs.net
  24.  */
  25. /* $Header: splint.cv  2.1  89/04/12 21:36:22  kenji  Exp $
  26.  * $Log: RCS/splint.cv $
  27.  * Revision 2.1  89/04/12 21:36:22  kenji
  28.  * BSD filename bug fixed
  29.  * 
  30.  * Revision 1.6  89/03/01 14:09:36  kenji
  31.  * Kenji welcome Naoshi one of the authors
  32.  * 
  33.  * Revision 1.5  89/02/22 20:39:10  kenji
  34.  * Modified for Microsoft C 5.1 Small Model by Naoshi Wakatabe
  35.  * 
  36.  * Revision 1.3  89/01/07 14:51:16  kenji
  37.  * unlink source file after successful conversion
  38.  * 
  39.  * Revision 1.2  89/01/07 11:48:44  kenji
  40.  * now display RCS header
  41.  * decoding file existence check included
  42.  * 
  43.  * Revision 1.1  89/01/06 23:47:40  kenji
  44.  * Initial revision
  45.  * 
  46.  */
  47.  
  48. static char *identfield = "$Header: splint.cv  2.1  89/04/12 21:36:22  kenji  Exp $";
  49.  
  50.  
  51. /* splint.c : encoding/decoding main program */
  52.  
  53. #include "splint.h"
  54. #include "getopt.h"
  55.  
  56. #define MODE_UNDEF 0
  57. #define DECODE_MODE 1
  58. #define ENCODE_MODE 2
  59.  
  60. #define PWDLEN 64
  61. #define FNAMLEN 32
  62. #define MAGIC_1 0x93
  63. #define MAGIC_2 0xB9
  64.  
  65. extern void spl_encode();
  66. extern void spl_decode();
  67.  
  68. /* global variables */
  69.  
  70. static int encmode, verbose;
  71. char spl_passwd[PWDLEN] = "";
  72.  
  73. /* encoding main routine */
  74.  
  75. void enc_file(orgname)
  76. char *orgname;
  77. {
  78.     static char splfile[FNAMLEN + 3], orgfile[FNAMLEN];
  79. #if defined(MSDOS)
  80.     static char o_ext[_MAX_EXT];
  81.     static char dummy[_MAX_PATH];
  82. #endif
  83. #if defined(__TURBOC__)
  84.     static char o_ext[MAXEXT];
  85. #endif
  86.     int i, j;
  87.     FILE *orgp, *splp;
  88.     struct stat statbuf;
  89.  
  90.     /* make splayed filename in cwd */
  91.  
  92. #ifdef BSD
  93.     char *p;
  94.     if ((p = strrchr(orgname, '/')) != NULL) {
  95.         strcpy(orgfile, p);
  96.         }
  97.     else {
  98.         strcpy(orgfile, orgname);
  99.         }
  100.     /* add extension ".SP" if UNIX */
  101.     i = strlen(orgfile);
  102.     if (i > FNAMLEN) {
  103.         i = FNAMLEN;
  104.         }
  105.     for (j = 0; j < i; j++) {
  106.         splfile[j] = orgfile[j];
  107.         }
  108.     splfile[i] = '.';
  109.     splfile[i + 1] = 'S';
  110.     splfile[i + 2] = 'P';
  111.     splfile[i + 3] = '\0';
  112. #ifdef DEBUG
  113.     fprintf(stderr, "%s, %s, %s\n", splfile, orgfile, orgname);
  114. #endif
  115. #endif
  116.  
  117. #ifdef __TURBOC__
  118.     /* change extension to ".spl" if MS-DOS */
  119.     fnsplit(orgname, NULL, NULL, orgfile, o_ext);
  120.     strcpy(splfile, orgfile);
  121.     strcat(orgfile, o_ext);
  122.     strcat(splfile, ".spl");
  123. #endif
  124. #ifdef MSDOS
  125.     /* change extension to ".spl" if MS-DOS(MSC) */
  126.     _splitpath(orgname, dummy, dummy, orgfile, o_ext);
  127.     strcpy(splfile, orgfile);
  128.     strcat(orgfile, o_ext);
  129.     strcat(splfile, ".spl");
  130. #endif
  131.  
  132.     /* check existence */
  133.     if (stat(splfile, &statbuf) == 0) {
  134.         char response[2];
  135.         response[0] = 'n';
  136.         fprintf(stderr, "splint: splayed file %s exists.\n", splfile);
  137.         fprintf(stderr, "Do you want to overwrite %s(Y/N)[N]? ", splfile);
  138.         fflush(stderr);
  139.         read(2, response, 2);
  140.         while (response[1] != '\n') {
  141.             if (read(2, response+1, 1) < 0) {
  142.                 perror("stderr"); break;
  143.                 }
  144.             }
  145.         if (response[0] != 'y') {
  146.             fprintf(stderr, "splint: %s not overwritten\n", splfile);
  147.             return;
  148.             }
  149.         }
  150.  
  151.     /* open files */
  152. #ifdef BSD
  153.     if((orgp = fopen(orgname, "r")) == NULL) {
  154.         fprintf(stderr, "splint: cannot open input file \"%s\" \n", orgname);
  155.         exit(-1);
  156.         }
  157.     if((splp = fopen(splfile, "w")) == NULL) {
  158.         fprintf(stderr, "splint: cannot open splay file \"%s\" \n", splfile);
  159.         exit(-1);
  160.         }
  161. #endif
  162. #if defined(__TURBOC__) || defined(MSDOS)
  163.     if((orgp = fopen(orgname, "rb")) == NULL) {
  164.         fprintf(stderr, "splint: cannot open input file \"%s\" \n", orgname);
  165.         exit(-1);
  166.         }
  167.     if((splp = fopen(splfile, "wb")) == NULL) {
  168.         fprintf(stderr, "splint: cannot open splay file \"%s\" \n", splfile);
  169.         exit(-1);
  170.         }
  171. #endif
  172.  
  173.     /* making a header */
  174.     putc(MAGIC_1, splp);
  175.     putc(MAGIC_2, splp);
  176.     putc(STYLE_ID, splp);
  177.     stat(orgname, &statbuf);
  178.     putc(statbuf.st_size & 0xff, splp);
  179.     putc((statbuf.st_size >> 8) & 0xff, splp);
  180.     putc((statbuf.st_size >> 16) & 0xff, splp);
  181.     putc((statbuf.st_size >> 24) & 0xff, splp);
  182.     fputs(orgfile, splp);
  183.     putc('\0', splp);
  184.     
  185.     /* encoding */
  186.     rewind(orgp);
  187.     spl_encode(orgp, splp);
  188.     
  189.     /* close files */
  190.     fclose(orgp);
  191.     fclose(splp);
  192.     /* delete original file */
  193.     unlink(orgname);
  194.  
  195. }
  196.  
  197. /* encoding main routine */
  198.  
  199. void dec_file(splname)
  200. char *splname;
  201. {
  202.     static char orgfile[FNAMLEN + 1];
  203.     int c, c1, c2, c3, i;
  204.     FILE *orgp, *splp;
  205.     struct stat statbuf;
  206.     long orgfsize;
  207.  
  208.     /* open splayed file */
  209.  
  210. #ifdef BSD
  211.     if((splp = fopen(splname, "rb")) == NULL) {
  212.         fprintf(stderr, "splint: cannot open splay input file \"%s\" \n", splname);
  213.         exit(-1);
  214.         }
  215. #endif
  216. #if defined(__TURBOC__) || defined(MSDOS)
  217.     if((splp = fopen(splname, "rb")) == NULL) {
  218.         fprintf(stderr, "splint: cannot open splay input file \"%s\" \n", splname);
  219.         exit(-1);
  220.         }
  221. #endif
  222.  
  223.     /* check MAGIC numbers */
  224.     rewind(splp);
  225.     c1 = getc(splp);
  226.     c2 = getc(splp);
  227.     c3 = getc(splp);
  228.     if (c1 != MAGIC_1 || c2 != MAGIC_2 || c3 != STYLE_ID) {
  229.         fprintf(stderr, "splint: bad file - magic number error\n");
  230.         exit(-1);
  231.         }
  232.     
  233.     /* get orgfile size */
  234.     c = getc(splp);
  235.     c1 = getc(splp);
  236.     c2 = getc(splp);
  237.     c3 = getc(splp);
  238.     orgfsize = ((long)c3 << 24) | ((long)c2 << 16) | 
  239.                ((long)c1 << 8) | (long)c;
  240.     
  241.     /* get original filename */
  242.     i = 0;
  243.     while (1){
  244.         c = getc(splp);
  245.         orgfile[i] = c;
  246.         if (c == '\0') break;
  247.         i++;
  248.         if (i > FNAMLEN) {
  249.             fprintf(stderr, "splint: bad file - filename error\n");
  250.             exit(-1);
  251.             }
  252.         }
  253.  
  254. #ifdef DEBUG
  255.     fprintf(stderr, "filename = %s, length = %ld\n", orgfile, orgfsize);
  256. #endif
  257.  
  258.     /* check existence */
  259.     if (stat(orgfile, &statbuf) == 0) {
  260.         char response[2];
  261.         response[0] = 'n';
  262.         fprintf(stderr, "splint: original file %s exists.\n", orgfile);
  263.         fprintf(stderr, "Do you want to overwrite %s(Y/N)[N]? ", orgfile);
  264.         fflush(stderr);
  265.         read(2, response, 2);
  266.         while (response[1] != '\n') {
  267.             if (read(2, response+1, 1) < 0) {
  268.                 perror("stderr"); break;
  269.                 }
  270.             }
  271.         if (response[0] != 'y') {
  272.             fprintf(stderr, "splint: %s not overwritten\n", orgfile);
  273.             fclose(splp);
  274.             return;
  275.             }
  276.         }
  277.  
  278.     /* open new original file */
  279.  
  280. #ifdef BSD
  281.     if((orgp = fopen(orgfile, "wb")) == NULL) {
  282.         fprintf(stderr, "splint: cannot open output file \"%s\" \n", orgfile);
  283.         exit(-1);
  284.         }
  285. #endif
  286. #if defined(__TURBOC__) || defined(MSDOS)
  287.     if((orgp = fopen(orgfile, "wb")) == NULL) {
  288.         fprintf(stderr, "splint: cannot open output file \"%s\" \n", orgfile);
  289.         exit(-1);
  290.         }
  291. #endif
  292.  
  293.     /* decoding */
  294.     spl_decode(splp, orgp);
  295.     
  296.     /* close files */
  297.     fclose(orgp);
  298.     fclose(splp);
  299.     
  300.     /* check file size */
  301.     stat(orgfile, &statbuf);
  302.     if (orgfsize == statbuf.st_size) {
  303.         unlink(splname);
  304.         }
  305.     else {
  306.         fprintf(stderr, "splint: decoded file %s has a wrong size, deleted\n", orgfile);
  307.         unlink(orgfile);
  308.         }
  309. }
  310.  
  311. /* display usage */
  312.  
  313. static void usage()
  314. {
  315.     fprintf(stderr,"Usage: splint -[deh] -g<passwd> filename\n");
  316.     fprintf(stderr,"-h to help\n");
  317. }
  318.  
  319. /* display help & copyright message */
  320.  
  321. static void disp_help()
  322. {
  323.     fprintf(stderr,"Splint: a splay-prefix data compression program\n");
  324.     fprintf(stderr,"Beta release version\n");
  325.     fprintf(stderr,"$Header: splint.cv  2.1  89/04/12 21:36:22  kenji  Exp $\n");
  326.     fprintf(stderr,"Copyright (c) 1988, 1989\n");
  327.     fprintf(stderr,"by Kenji Rikitake and Naoshi Wakatabe.\n");
  328.     fprintf(stderr,"All Rights Reserved.\n");
  329.     putc('\n', stderr);
  330.     usage();
  331.     fprintf(stderr,"   -d: decode from splayed file\n");
  332.     fprintf(stderr,"   -e: encode to splayed file\n");
  333.     fprintf(stderr,"   -g: encrypt/decrypt with following password\n");
  334.     fprintf(stderr,"   -h: display this help message\n");
  335.     putc('\n', stderr);
  336. }
  337.  
  338. /* main routine */
  339.  
  340. int main(argc, argv)
  341. int argc;
  342. char *argv[];
  343. {
  344.     int option;
  345.  
  346.     encmode = MODE_UNDEF;
  347.  
  348.     /* stdin = non-buffering keyboard */
  349.     setbuf(stdin, NULL);
  350.  
  351.     /* parsing options */
  352.     while ((option = getopt(argc, argv, "deg:hv")) != EOF)
  353.         switch (option) {
  354.         case 'd':
  355.             encmode = DECODE_MODE;
  356.             break;
  357.         case 'e':
  358.             encmode = ENCODE_MODE;
  359.             break;
  360.         case 'g':
  361.             if (strlen(optarg) <= PWDLEN) {
  362.                 strcpy(spl_passwd, optarg);
  363.                 }
  364.             else {
  365.                 fprintf(stderr, "splint: encrypt password too long\n");
  366.                 usage();
  367.                 exit(-1);
  368.                 }
  369.             break;
  370.         case 'h':
  371.             disp_help();
  372.             exit(0);
  373.             break;
  374.         case '?':
  375.             usage();
  376.             exit(-1);
  377.             break;
  378.         default:
  379.             break;
  380.         }
  381.  
  382.     if (encmode == MODE_UNDEF) {
  383.         fprintf(stderr, "splint: tell me what should I do\n");
  384.         usage();
  385.         exit(-1);
  386.         }
  387.  
  388.     /* solve wildcarded filenames */
  389.     
  390.     while (optind < argc) {
  391.         switch (encmode) {
  392.             case DECODE_MODE:
  393.                 fprintf(stderr, "Decoding %s:\n", argv[optind]);
  394.                 dec_file(argv[optind]);
  395.                 break;
  396.             case ENCODE_MODE:
  397.                 fprintf(stderr, "Encoding %s:\n", argv[optind]);
  398.                 enc_file(argv[optind]);
  399.                 break;
  400.             default:
  401.                 fprintf(stderr, "splint: internal error in enc/dec loop\n");
  402.                 exit(-1);
  403.                 break;
  404.             }
  405.         optind++;
  406.         }
  407.     
  408.     exit(0);
  409. }
  410.